package com.copro.chemdb.result;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.ihelpuoo.db.sql.SQLSegment;
import org.ihelpuoo.util.Pager;

import com.copro.simple.Application;
import com.copro.simple.SimpleException;
import com.copro.simple.db.FreeCallback;
import com.copro.simple.db.QueryCallback;
import com.copro.simple.db.QueryListCallBack;
import com.copro.simple.db.SQLSet;

public class ResultUtils {

	/**
	 * Provide the query function for list
	 * 
	 * @author zozoh
	 * 
	 */
	static class ListGetter extends QueryListCallBack {

		private List<Result> list;

		public ListGetter(List<Result> list) {
			super();
			this.list = list;
		}

		public ListGetter(List<Result> list, Pager pager) {
			super(pager);
			this.list = list;
		}

		public List<Result> getList() {
			return this.list;
		}

		@Override
		protected void makeObject(ResultSet rs) throws SQLException {
			list.add(new Result(rs));
		}

	}

	static class AnswerDetailGetter implements QueryCallback {

		private Answer answer;

		public AnswerDetailGetter(Answer answer) {
			this.answer = answer;
		}

		public Answer getObject() {
			return this.answer;
		}

		@Override
		public void exec(ResultSet rs) throws SQLException {
			if (rs.first())
				this.answer = new Answer(rs);
		}

	}

	/**
	 * Provide the query function for one object
	 * 
	 * @author zozoh
	 * 
	 */
	static class DetailGetter implements QueryCallback {

		private Result result;

		public DetailGetter(Result ques) {
			this.result = ques;
		}

		public Result getObject() {
			return this.result;
		}

		@Override
		public void exec(ResultSet rs) throws SQLException {
			if (rs.first())
				this.result = new Result(rs);
		}

	}

	static class SaveToDatabase implements FreeCallback {

		private Result result;
		private int saveType;

		public SaveToDatabase(Result result, int saveType) {
			this.result = result;
			this.saveType = saveType;
		}

		@Override
		public void exec(Connection conn, SQLSet sqls) throws SQLException {
			Application app = (Application) sqls;
			Statement stm = conn.createStatement(
					ResultSet.TYPE_SCROLL_INSENSITIVE,
					ResultSet.CONCUR_UPDATABLE);
			SQLSegment sql = null;

			/* If result is exsited clear answer at first */
			if (result.getId() > 0) {
				if (Result.FROM_QUEST == saveType)
					sql = app.getSQL("clearAnswer_ques");
				else
					sql = app.getSQL("clearAnswer_db");

				sql.set("resultId", result.getId());
				stm.execute(sql.toString());

				sql = app.getSQL("updateResult");
				fillSaveResultSQL(app, sql);
				stm.execute(sql.toString());
			} else { /* If create a new result */
				sql = app.getSQL("addResult");
				fillSaveResultSQL(app, sql);
				result = (Result) app.insertWithoutCommit(sql.toString(),
						"maxResult", result, "id", stm);
			}

			/* looping insert answer */
			sql = app.getSQL("addAnswer");
			Iterator<Answer> it = result.getAnswers().iterator();
			while (it.hasNext()) {
				sql.clearAll();
				Answer an = it.next();
				sql.set("subjectId", an.getSubjectId());
				sql.set("strValue", an.getStrValue());
				sql.set("intValue", an.getIntValue());
				sql.set("text", an.getText());
				sql.set("resultId", result.getId());
				stm.execute(sql.toString());
			}

		}

		private void fillSaveResultSQL(Application app, SQLSegment sql) {
			sql.set("id", result.getId());
			// TODO ZZH: Use the real session user.
			sql.set("user", result.getUser());
			sql.set("quesId", result.getQuesId());
			sql.set("parentId", result.getParentId() > 0 ? result.getParentId()
					: "NULL");
			sql.set("type", result.getType());
			sql.set("createTime", app
					.formatDatetime(System.currentTimeMillis()));
		}

	}

	static Result saveToDatabase(Application app, Result result, int saveType)
			throws SimpleException {
		SaveToDatabase callback = new SaveToDatabase(result, saveType);
		app.exec(callback);
		return callback.result;
	}

	public static Result getResult(Application app, int resultId)
			throws SimpleException {
		DetailGetter callback = new DetailGetter(new Result());
		SQLSegment sql = app.getSQL("getResult");
		sql.set("resultId", resultId);
		app.query(sql.toString(), callback);
		return callback.getObject();
	}

	public static List<Result> getResultList(Application app, int questionId,
			Pager pager) throws SimpleException {
		ListGetter callback = new ListGetter(new LinkedList<Result>(), pager);
		SQLSegment sql = app.getSQL("getResultList");
		sql.set("id_T_questionnaire", questionId <= 0 ? "NULL" : questionId);
		app.query(sql.toString(), callback);
		return callback.getList();
	}

	public static List<Result> getDBQuesResultList(Application app,
			int questionId, Pager pager) throws SimpleException {
		ListGetter callback = new ListGetter(new LinkedList<Result>(), pager);
		SQLSegment sql = app.getSQL("getDBQuesResultList");
		sql.set("id_T_questionnaire", questionId <= 0 ? "NULL" : questionId);
		app.query(sql.toString(), callback);
		return callback.getList();
	}

	public static List<Result> getSubResultList(Application app, int parentId)
			throws SimpleException {
		ListGetter callback = new ListGetter(new LinkedList<Result>());
		SQLSegment sql = app.getSQL("getSubResultList");
		sql.set("parentId", parentId <= 0 ? "NULL" : parentId);
		app.query(sql.toString(), callback);
		return callback.getList();
	}

	public static List<Result> getDBQuesSubResultList(Application app,
			int parentId) throws SimpleException {
		ListGetter callback = new ListGetter(new LinkedList<Result>());
		SQLSegment sql = app.getSQL("getDBQuesSubResultList");
		sql.set("parentId", parentId <= 0 ? "NULL" : parentId);
		app.query(sql.toString(), callback);
		return callback.getList();
	}

	public static List<Answer> getAnswerList(Application app, int resultId,
			int subjectId) throws SimpleException {
		AnswerListGetter callback = new AnswerListGetter(
				new LinkedList<Answer>());
		SQLSegment sql = app.getSQL("getResultAnswers");
		sql.set("id_T_subject", subjectId <= 0 ? "NULL" : subjectId);
		sql.set("resultId", resultId <= 0 ? "NULL" : resultId);
		app.query(sql.toString(), callback);
		return callback.getList();
	}

	public static List<Answer> getAnswerList(Application app, int subjectId)
			throws SimpleException {
		AnswerListGetter callback = new AnswerListGetter(
				new LinkedList<Answer>());
		SQLSegment sql = app.getSQL("getSubjectAnswers");
		sql.set("id_T_subject", subjectId <= 0 ? "NULL" : subjectId);
		app.query(sql.toString(), callback);
		return callback.getList();
	}

	public static List<String> renderSubjects(Application app, int questionId,
			Result result, String prefix) throws SimpleException {
		List<String> strSubjects = null;
		SegmentWriter sw = new SegmentWriter(prefix);
		strSubjects = sw.renderSubjects(app, questionId, result);
		return strSubjects;
	}

}
